package com.rongkang.interview.jvm.oom;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.TimeUnit;

/**
 * @Description:
 * @author: 荣康
 * @date: 2021/12/17
 * *
 * @Description: java.lang.stackOverFlowError  java栈溢出，递归方法，造成栈溢出   这个是错误，不是异常
 * java.lang.OutOfMemoryError 这个是错误，不是异常
 * java.lang.OutOfMemoryError java heap space          创建了很多对象，堆内存撑爆了
 * java.lang.OutOfMemoryError GC overhead limit exceeded           GC回收时间过长，连续多次GC清理的内存，
 * 很快就被再次填满，迫使GC再次执行，CPU利用率一直是100%，GC却没有任何成果（98%时间用来GC,回收了不到2%的内存）
 * java.lang.OutOfMemoryError
 * java.lang.OutOfMemoryError   MetaSpace
 * java.lang.OutOfMemoryError  unable to create new native thread     不能够创建更多的线程了
 * 准确的来讲，这个错误，是跟对应的平台有关的
 *      导致原因：
 *          应用创建了太多线程，一个应用进程创建多个线程，超过系统承载极限
 *          服务器不允许你的应用创建这么多线程，linux系统默认允许单个进程可以创建的线程数是1024个
 *          你的应用如果想超过1024限制，可以通过修改linux服务器配置，扩大linux默认限制
 */
public class StackOverFlowErrorDemo {
    public static void main(String[] args) {

    }

    //OOM   unable to create new native thread   不能创建更过的线程
    //这个方法需要弄到linux上才能验证，linux上默认一个进程创建最大线程为1024个
    //非root用户验证更为明显
    private static void unableToCreateNewNativeThread() {
        for (int i = 0; ; i++) {
            System.out.println("****************i = " + i);
            new Thread(()->{
                try {
                    TimeUnit.SECONDS.sleep(Integer.MAX_VALUE);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            },String.valueOf(i)).start();
        }
    }

    //OOM  GC overhead limit exceeded   不断往list集合中插入string对象，直到启动GC回收,一直在GC
    //设置参数 -Xms10m -Xmx10m -XX:+PrintGCDetails -XX:MaxDirectMemorySize=5m
    private static void gcOverheadLimitExceeded() {
        int i =0;
        List<String> list = new ArrayList<>();
            while (true){
                list.add(String.valueOf(++i).intern());
            }
    }

    //OOM java heap space
    private static void javaHeapSpaceDemo() {
        //设置参数-Xms10m -Xms10m，直接创建一个大的byte字节数组，或者一直加
        //byte[] bytes = new byte[50 * 1024 * 1024];
        String str = "rongkang";
        while (true) {
            str += str + new Random().nextInt(1111111111) + new Random().nextInt(222222222);
        }
    }

    //栈内存溢出
    private static void stackOverFlowError() {
        stackOverFlowError();
    }

    static  class OOMTest{  }

}
